/*
 * Copyright 2009 BioTeam Inc
 * 
 * Licensed under License GNU LESSER GENERAL PUBLIC LICENSE version 3.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 * 
 * http://www.gnu.org/copyleft/lesser.html
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */
package net.bioteam.appweb.gwt.apps.server.user;

import java.util.Iterator;
import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.EntityTransaction;
import javax.persistence.FlushModeType;
import javax.persistence.Query;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import net.bioteam.appweb.gwt.apps.clientandserver.ServerException;
import net.bioteam.appweb.gwt.apps.clientandserver.user.AdminUserAction;
import net.bioteam.appweb.gwt.apps.clientandserver.user.UserAction;
import net.bioteam.appweb.gwt.apps.clientandserver.user.UserRet;
import net.bioteam.appweb.gwt.apps.server.MyAuthException;
import net.bioteam.appweb.gwt.apps.server.MyRemoteServiceServlet;
import net.bioteam.common.user.User;
import net.bioteam.common.utils.MyEntityManager;

public class AdminUserActionImpl extends MyRemoteServiceServlet implements AdminUserAction
{

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	public final static Log logger = LogFactory.getLog(AdminUserActionImpl.class);

	public UserRet getUsers(int start, int limit, String sort, String direction) throws ServerException
	{

		User user = (User) getThreadLocalRequest().getSession(true).getAttribute("user");
		if (!user.getRole().equals("admin"))
		{
			throw new MyAuthException(HttpServletResponse.SC_FORBIDDEN, "You do not have permission to access thi");
		}
		EntityManager em = MyEntityManager.getEntityManager();
		try
		{
			if (sort != null)
			{
				sort = "u." + sort;
			} else
			{
				sort = "u.name";
			}
			if (direction == null)
			{
				direction = "desc";
			}
			EntityTransaction tx = em.getTransaction();
			tx.begin();
			UserRet ret = new UserRet();
			Query totalQuery = em.createNamedQuery("numofusers");
			Number result = (Number) totalQuery.getSingleResult();
			int count = result.intValue();
			ret.count = count;

			Query query = em.createQuery("select u from User u  order by " + sort + " " + direction);
			query.setMaxResults(limit);
			query.setFirstResult(start);
			List lists = query.getResultList();
			User users[] = new User[lists.size()];
			int i = 0;
			for (Iterator iter = lists.iterator(); iter.hasNext(); i++)
			{
				User u = (User) iter.next();
				users[i] = u;
			}
			ret.users = users;

			tx.commit();
			return ret;
		} catch (Exception e)
		{
			logger.warn("user jobs error", e);
			throw new ServerException(e.getMessage());
		}

	}

	public User addUser(User cuser) throws ServerException
	{
		User user = (User) getThreadLocalRequest().getSession().getAttribute("user");
		if (!user.getRole().equals("admin"))
		{
			throw new MyAuthException(HttpServletResponse.SC_FORBIDDEN, "You do not have permission to access thi");
		}
		try
		{
			EntityManager em = MyEntityManager.getEntityManager();
			EntityTransaction tx = em.getTransaction();
			em.setFlushMode(FlushModeType.COMMIT);
			try
			{
				tx.begin();
				em.persist(cuser);
				tx.commit();
			} catch (RuntimeException e1)
			{
				try
				{
					tx.rollback();
				} catch (Exception e2)
				{
					// ignore.
				}
				throw e1;
			}
			return cuser;

		} catch (Exception e)
		{
			logger.warn("user error", e);
			throw new ServerException(e.getMessage());
		}
	}
	public User[] saveUsers(User[] users) throws ServerException
	{
		try
		{
			EntityManager em = MyEntityManager.getEntityManager();
			EntityTransaction tx = em.getTransaction();
			em.setFlushMode(FlushModeType.COMMIT);
			Query updateQuery = em.createNamedQuery("updateuser");
			try
			{
				tx.begin();
				for (int i = 0; i < users.length; i++)
				{
					User u = users[i];
					updateQuery.setParameter("userid", u.getUserid());
					updateQuery.setParameter("email", u.getEmail());
					updateQuery.setParameter("active", u.isActive());
					updateQuery.setParameter("password", u.getPassword());
					updateQuery.setParameter("role", u.getRole());
					updateQuery.setParameter("dailyquote", u.getUserInfo().getDailyquote());
					// always execute automatically
					int rows = updateQuery.executeUpdate();

					if (rows != 1)
					{
						logger.warn("no row affacted by status update");
					} else
					{
						logger.info("status is updated for " + u.getUserid());
					}

					// returned instance is managed instance.
					// argument u is detached instance. Since some field
					// such as username is not updatable, we need to return
					// the managed instance and communicate it back to client.
					u = em.find(User.class, u.getUserid());
					em.refresh(u);
					users[i] = u;
				}
				tx.commit();
			} catch (RuntimeException e1)
			{
				try
				{
					tx.rollback();
				} catch (Exception e2)
				{
					// ignore.
				}
				throw e1;
			}
			return users;

		} catch (Exception e)
		{
			logger.warn("user error", e);
			throw new ServerException(e.getMessage());
		}
	}

	public String deleteUsers(String[] ids) throws ServerException
	{
		User user = (User) getThreadLocalRequest().getSession().getAttribute("user");
		try
		{
			EntityManager em = MyEntityManager.getEntityManager();
			EntityTransaction tx = em.getTransaction();
			em.setFlushMode(FlushModeType.COMMIT);
			try
			{
				tx.begin();
				for (String id : ids)
				{
					User u = em.find(User.class, Long.parseLong(id));
					if (u == null)
						continue;

					em.remove(u);

					// TODO clean user artifact file: template files, job
					// directory, temporary directory
				}
				tx.commit();
			} catch (RuntimeException e1)
			{
				try
				{
					tx.rollback();
				} catch (Exception e2)
				{
					// ignore.
				}
				throw e1;
			}
			return "Requested users are deleted";

		} catch (Exception e)
		{
			logger.warn("user error", e);
			throw new ServerException(e.getMessage());
		}
	}

	
	
}
